// SPDX-FileCopyrightText: 2022-2025 CASTest Corporation Limited
// SPDX-FileCopyrightText: 2022-2025 Institute of Computing Technology, Chinese Academy of Sciences
// SPDX-License-Identifier: LGPL-v3

#ifndef PATTERNS_H
#define PATTERNS_H

#include "Define.h"
#include "STILparser.h"
#include "Value.h"
#include "Gate.h"
#include "Errors.h"

#include <cstdint>
#include <vector>
#include <string>
#include <iostream>

using namespace std;

class Patterns {
private:
    //store pi value
    //1st dim represent different pi
    //2nd dim represent different word
    vector<vector<Value>> _parallel_patterns_pi;
    // store po value
    vector<vector<Value>> _parallel_patterns_po;

    // store si so value
    //1st represent different dff gate
    vector<vector<vector<Value>>> _parallel_load_value;
    vector<vector<vector<Value>>> _parallel_unload_value;

    //1st dim represent different word_id
    //2nd dim store gate_id clock_value
    vector<vector<Value>> _parallel_pattern_clock_value;


    //1st dim represent different pattern
    //2nd dim represent pattern pi value
    vector<vector<Value>> _serial_patterns_pi;
    vector<vector<Value>> _serial_patterns_po;
    vector<vector<vector<Value>>> _serial_load_value;
    vector<vector<vector<Value>>> _serial_unload_value;

    //1st dim represent different pattern
    //2nd dim represent pattern pi clock id
    vector<vector<size_t>> _serial_pattern_clock_ids;
    vector<vector<Value>> _serial_pattern_clock_value;


    size_t _num_pi;
    size_t _num_po;
    size_t _num_scan_chain;
    size_t _num_pattern;
    size_t _num_word;
    int last_parallel_pattern_bit_num;
public:
    // TODO: optimize to private and add support function
    // first store clock pi id
    // second store clock start value 0 represent 010, 1 represent 101

    map<int, int> _clock_start_value;
    vector<int> _clock_pi_ids;

    Patterns(size_t num_pi, size_t num_po, size_t num_scan_chain)
        :_num_pi(num_pi), _num_po(num_po), _num_scan_chain(num_scan_chain),
         _num_word(0),_num_pattern(0)
        {}

    Patterns()
        :_num_pi(0), _num_po(0), _num_scan_chain(0),
         _num_word(0),_num_pattern(0)
        {}


    void SetNumPo(size_t num){
        _num_po = num;
    }
    void SetNumPI(size_t num){
        _num_pi = num;
    }
    void SetNumScanChain(size_t num){
        _num_scan_chain = num;
    }

    unordered_map<int, int> CreateSignalOrderMap(vector<Gate *>& vy_pi_gates,
                                                 vector<string> stil_singal);

    void ReadPatternFromStil(const string& stil_file_name,
                            unordered_map<int, int>& stil_vy_pi_order,
                            unordered_map<int, int> &stil_vy_po_order);

    int  ConvertSerialToParallelPattern();

    void PrintSerialPatternValue(const vector<vector<Value>>& patterns);
    void PrintSerialScanValue(const vector<vector<vector<Value>>>& scan_value);

    const vector<vector<Value>>& GetParallelPatternsPi() const {
        return _parallel_patterns_pi;
    }
    const vector<vector<Value>>& GetParallelPatternsPo() const {
        return _parallel_patterns_po;
    }
    const vector<vector<vector<Value>>>& GetParallelLoadValue() const {
        return _parallel_load_value;
    }
    const vector<vector<vector<Value>>>& GetParallelUnloadValue() const {
        return _parallel_unload_value;
    }
    const vector<vector<Value>>& GetParallelPatternClockValues() const {
        return _parallel_pattern_clock_value;
    }
    const vector<vector<Value>>& GetSerialPatternsPi() const {
        return _serial_patterns_pi;
    }
    const vector<vector<Value>>& GetSerialPatternsPo() const {
        return _serial_patterns_po;
    }
    const vector<vector<vector<Value>>>& GetSerialLoadValue() const {
        return _serial_load_value;
    }
    const vector<vector<vector<Value>>>& GetSerialUnloadValue() const {
        return _serial_unload_value;
    }
    const vector<vector<size_t>>& GetSerialPatternClockIds() const {
        return _serial_pattern_clock_ids;
    }
    const vector<vector<Value>>& GetSerialPatternClockValue() const {
        return _serial_pattern_clock_value;
    }
    size_t GetPatternNums() const {
        return _num_pattern;
    }
};

#endif // PATTERNS_H
